package com.xunlai.infra.permission.business.service.impl;

import com.xunlai.infra.permission.business.converter.InvitationCodeConverter;
import com.xunlai.infra.permission.business.converter.RouteConverter;
import com.xunlai.infra.permission.business.dao.entity.InvitationCode;
import com.xunlai.infra.permission.business.dao.entity.RouteInfo;
import com.xunlai.infra.permission.business.dao.repository.InvitationCodeRepository;
import com.xunlai.infra.permission.business.service.InvitationCodeService;
import com.xunlai.infra.permission.business.vo.invitation.InvitationCodeCreateVo;
import com.xunlai.infra.permission.business.vo.invitation.InvitationCodeListVo;
import com.xunlai.infra.permission.business.vo.invitation.InvitationUpdateVo;
import com.xunlai.infra.permission.business.vo.route.RouteListVo;
import com.xunlai.infra.permission.common.exception.ExceptionCodeEnum;
import com.xunlai.infra.permission.common.exception.PermissionBusinessException;
import com.xunlai.infra.permission.common.vo.BasePageRespVo;
import com.xunlai.infra.permission.storage.entity.UserAccount;
import com.xunlai.infra.permission.storage.repository.UserAccountRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.relational.core.conversion.DbActionExecutionException;
import org.springframework.stereotype.Service;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Optional;

/**
 * @author liang
 * @date 8/21/23 10:05 PM
 */
@Service
public class InvitationCodeServiceImpl implements InvitationCodeService {

    private final Logger logger = LoggerFactory.getLogger(InvitationCodeServiceImpl.class);
    private InvitationCodeRepository invitationCodeRepository;

    private UserAccountRepository userAccountRepository;

    @Override
    public Long createInvitationCode(InvitationCodeCreateVo invitationCodeCreateVo) throws PermissionBusinessException {
        InvitationCode invitationCode = InvitationCodeConverter.INSTANCE.convertCreateVo2Entity(invitationCodeCreateVo);
        try {
            Long inviterId = invitationCodeCreateVo.getInviterId();
            if(inviterId != null) {
                Optional<UserAccount> userAccountOptional = userAccountRepository.findById(inviterId);
                userAccountOptional.ifPresent(userAccount -> invitationCode.setInviterAccount(userAccount.getAccount()));
            }
            InvitationCode save = invitationCodeRepository.save(invitationCode);
            return save.getId();
        }catch (DbActionExecutionException e){
            Throwable cause = e.getCause();
            if(cause instanceof SQLIntegrityConstraintViolationException){
                logger.error(e.getMessage(),e);
                throw new PermissionBusinessException(ExceptionCodeEnum.DATA_REPEAT);
            }else {
                throw e;
            }
        }
    }

    @Override
    public void bindInviterAccount(Long id, InvitationUpdateVo invitationUpdateVo) {
        Optional<InvitationCode> invitationCodeOptional = invitationCodeRepository.findById(id);
        if(invitationCodeOptional.isEmpty()) {
            return;
        }
        InvitationCode invitationCode = invitationCodeOptional.get();
        Long inviterId = invitationUpdateVo.getInviterId();
        if(inviterId != null) {
            invitationCode.setInviterId(invitationUpdateVo.getInviterId());
            Optional<UserAccount> userAccountOptional = userAccountRepository.findById(inviterId);
            userAccountOptional.ifPresent(userAccount -> invitationCode.setInviterAccount(userAccount.getAccount()));
        }
        invitationCodeRepository.save(invitationCode);
    }

    @Override
    public BasePageRespVo<InvitationCodeListVo> listInvitationCode(Integer pageNum, Integer pageSize) {
        pageNum = (pageNum == null || pageNum < 1) ? 1 : pageNum;
        int size = (pageSize == null || pageSize <= 0) ? 10 : pageSize;
        Page<InvitationCode> invitationCodePage = invitationCodeRepository.findAll(PageRequest.of(pageNum - 1, size));
        List<InvitationCodeListVo> invitationCodeListVos = invitationCodePage.getContent().stream().map(InvitationCodeConverter.INSTANCE::convertEntity2ListVo).toList();
        return new BasePageRespVo<>(invitationCodeListVos,pageNum,size,invitationCodePage.getTotalElements(), invitationCodePage.getTotalPages());
    }

    @Autowired
    public void setInvitationCodeRepository(InvitationCodeRepository invitationCodeRepository) {
        this.invitationCodeRepository = invitationCodeRepository;
    }

    @Autowired
    public void setUserAccountRepository(UserAccountRepository userAccountRepository) {
        this.userAccountRepository = userAccountRepository;
    }
}
